import { isString } from "../../shared";
import { NodeTypes } from "./ast";
import { CREATE_ELEMENT_VNODE, TO_DISPLAY_STRING, helperMapName } from "./runtimeHelpers";

export function generate(ast) {
    const context = createCodegenContext();
    // 进行 字符的 拼接
    const { push } = context;

    //  处理导入逻辑
    genFunctionPreamble(ast,context)

    const functionName = "render"
    const args = ["_ctx", "_cache"]
    const signature = args.join(", ")

    console.log('ast+++++++++',ast);
    
    push(`function ${functionName}(${signature}){`)
    push(`return `)
    genNode(ast.codegenNode,context)
    push("}")

    return {
        code:context.code
    }
}

function genFunctionPreamble (ast,context) {
    const { push } = context
    const VueBinging = 'Vue'
    const aliasHelper = (s) => `${helperMapName[s]}:_${helperMapName[s]}`
    if(ast.helpers.length > 0) {
        push(`const { ${ast.helpers.map(aliasHelper).join(', ')} } = ${VueBinging}`)
    }
    push('\n')
    push("return ")
}

function genNode(node: any,context) {
    switch (node.type) {
        case NodeTypes.TEXT:
            genText(node,context)
            break;
        case NodeTypes.INTERPOLATION:
            genInterpolation(node,context)
            break;
        case NodeTypes.SIMPLE_EXPRESSION:
            console.log('11111111',node);
            genExpression(node,context)
            break;
        case NodeTypes.ELEMENT:
            genElement(node,context)
            break;
        case NodeTypes.COMPOUND_EXPRESSION:
            genCompoundExpression(node,context)
            break;

        default:
            break;
    }  
}

function genCompoundExpression(node: any, context: any) {
    const { push } = context
    const children = node.children
    for (let i = 0; i < children.length; i++) {
        const child = children[i];
        if(isString(child)) {
            push(child)
        } else {
            genNode(child,context)
        }
    }
}

function genText(node: any, context: any) {
    const { push } = context
    push(`'${node.content}'`)
}

function genElement(node: any, context: any) {
    const { push,helper } = context
    const { tag,props,children } = node
    push(`${helper(CREATE_ELEMENT_VNODE)}(`)
    genNodeList(genNullable([tag,props,children]),context) 
    push(")")
}

function genNodeList(nodes,context) {
    const { push } = context
    for (let i = 0; i < nodes.length; i++) {
        const node = nodes[i];
        if(isString(node)) {
            push(node)
        } else {
            genNode(node,context)
        }
        if(i < nodes.length - 1) { 
            push(", ")
        }
    }
}

// 通过对参数进行非空的统一判断
function genNullable(args) {
    return args.map((arg) => arg || "null")
}

function genExpression(node: any, context: any) {
    const { push } = context
    push(`${node.content}`)
}

function genInterpolation(node: any, context: any) {
    const { push,helper } = context
    push(`${helper(TO_DISPLAY_STRING)}(`)
    genNode(node.content, context)
    push(")")
}

function createCodegenContext():any {
    const context = {
        code: "",
        push(source) {
            context.code += source
        },
        helper(key) {
            return `_${helperMapName[key]}`
        }
    }
    return context
}




